package com.jimmyhsu.ecnudaowei.coursetable.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import java.util.Calendar;

/**
 * Created by jimmyhsu on 2017/3/26.
 */

public class CourseTableCondensedLayout extends View {

    private int mStartNumber = -1;
    private int mEndNumber = -1;
    private int mSelectedDay = -1;

    public static final int DAY_COUNT = 7;
    public static final int DAY_COURSE_COUNT = 11;
    private static final String MONTH = "月";
    public static final String[] NUMBERS = new String[]{"一", "二", "三", "四", "五", "六", "日"};
    private static final int[] CARD_COLORS = new int[]{0xFFE4E9F1, 0xFF70C3F7, 0xFFFDB650,
            0xFF47DFC6, 0xFF70C3F7, 0xFF43D894, 0xFF70C3F7, 0xFFFB9EC9};

    private Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private float mTopHeight;
    private int mTopFrameMargin = dp2px(5, getContext());
    private float mFirstColWidth;
    private float mColWidth;
    private Typeface mTypeface;

    private int mWidth;
    private int mHeight;
    private float mRowHeight;
    private float mIndicatorHeight;
    private int mTextColor = 0xFF1E3F5C;
    private int mTextColorDark = 0xFF48707F;
    private int mBackgroundDark = 0xFFF2F8F7;
    private int mTodayBackground = 0xFFABF4EE;
    private int mDividerColor = 0xFFE4ECEE;
    private int mTextSmallSize = 11;
    private int mTextBigSize = 16;
    private int mSelectedColor = 0xFFD9E5EE;

    public CourseTableCondensedLayout(Context context) {
        this(context, null);
    }

    public CourseTableCondensedLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public CourseTableCondensedLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mTypeface = Typeface.createFromAsset(context.getAssets(), "Roboto-Condensed.ttf");
    }

    public void setPeriod(int day, int start, int end) {
        this.mStartNumber = start;
        this.mEndNumber = end;
        this.mSelectedDay = day;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mStartNumber < 0 || mEndNumber < 0) return;
        drawUpperBackground(canvas);
        drawUpperText(canvas);
        drawRow(canvas);
        drawDashPath(canvas);
        drawIndicator(canvas);
    }

    private void drawUpperBackground(Canvas canvas) {
        mBackgroundPaint.setColor(mBackgroundDark);
        mBackgroundPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, mWidth, mTopHeight, mBackgroundPaint);
    }

    private void drawUpperText(Canvas canvas) {
        Calendar calendar = Calendar.getInstance();
        String currMonth = String.valueOf(calendar.get(Calendar.MONTH) + 1) + "\r\n月";
        drawText(canvas, 12, currMonth, 0);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        String[] dates = new String[7];
        int today = initDays(dates, dayOfWeek, dayOfMonth);
        for (int i = 0; i < 7; i++) {
            if (i == today) {
                drawTodayRect(canvas, i);
            }
            drawText(canvas, i == today ? mTextBigSize : mTextSmallSize,
                    dates[i], mFirstColWidth + mColWidth * i);
        }
        drawDivider(canvas);
    }

    private int initDays(String[] dst, int dayOfWeek, int dayOfMonth) {
        int index = dayOfWeek - 2 >= 0 ? dayOfWeek - 2 : 6;
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        int tempIndex = index;
        int count = 0;
        while (index > -1) {
            dst[index] = "周" + NUMBERS[index] + "\r\n" + c.get(Calendar.DAY_OF_MONTH) + "日";
            index--;
            c.add(Calendar.DATE, -1);
            count++;
        }
        index = tempIndex + 1;
        c.add(Calendar.DATE, count + 1);
        while (index < 7) {
            dst[index] = "周" + NUMBERS[index] + "\r\n" + c.get(Calendar.DAY_OF_MONTH) + "日";
            index++;
            c.add(Calendar.DATE, 1);
        }
        return dayOfWeek - 2 >= 0 ? dayOfWeek - 2 : 6;
    }

    private void drawTodayRect(Canvas canvas, int index) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mTodayBackground);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawRect(mFirstColWidth + index * mColWidth,
                0,
                mFirstColWidth + (index + 1) * mColWidth,
                mTopHeight,
                paint);
    }

    private void drawDivider(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mDividerColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1);
        canvas.drawLine(0, mTopHeight, mWidth, mTopHeight, paint);
    }

    private void drawRow(Canvas canvas) {
        canvas.drawRect(0, mTopHeight, mFirstColWidth, mHeight, mBackgroundPaint);
        String periodText = (mStartNumber + 1) + "-" + (mEndNumber + 1);
        mTextPaint.setTextSize(sp2px(11, getContext()));
        mTextPaint.setColor(mTextColorDark);
        float textWidth = mTextPaint.measureText(periodText, 0, periodText.length());
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float textHeight = (float) Math.ceil(fontMetrics.descent - fontMetrics.ascent);
        canvas.drawText(periodText,
                mFirstColWidth / 2f - textWidth / 2f,
                mTopHeight + (mRowHeight - mIndicatorHeight) / 2f + textHeight / 2f,
                mTextPaint);
        mBackgroundPaint.setColor(mSelectedColor);
        float l = mFirstColWidth + mSelectedDay * mColWidth;
        canvas.drawRect(l,
                mTopHeight, l + mColWidth,
                mHeight - mIndicatorHeight, mBackgroundPaint);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mTextColorDark);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(sp2px(1, getContext()));
        float startX = l + 0.25f * mColWidth;
        float startY = mTopHeight + 0.5f * (mRowHeight - mIndicatorHeight);
        canvas.drawLine(startX, startY, l + 0.75f * mColWidth, startY, paint);
        canvas.drawLine(l + 0.5f * mColWidth, startY - 0.25f * (mRowHeight - mIndicatorHeight),
                l + 0.5f * mColWidth, startY + 0.25f * (mRowHeight - mIndicatorHeight), paint);
    }

    private void drawIndicator(Canvas canvas) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setColor(mSelectedColor);
        Path path = new Path();
        path.moveTo(-0.1f * mColWidth, 0);
        path.lineTo(0.1f * mColWidth, 0);
        path.lineTo(0, -mIndicatorHeight);
        path.close();
        canvas.save();
        canvas.translate(mFirstColWidth + mColWidth * mSelectedDay + 0.5f * mColWidth, mHeight);
        canvas.drawPath(path, paint);
        canvas.restore();
    }

    private void drawDashPath(Canvas canvas) {
        DashPathEffect dashPathEffect = new DashPathEffect(
                new float[]{dp2px(6, getContext()), dp2px(6, getContext())}, 1);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(mBackgroundDark);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(dp2px(2, getContext()));
        paint.setPathEffect(dashPathEffect);

        Path path = new Path();
        path.moveTo(0, mHeight - mIndicatorHeight);
        path.lineTo(mWidth, mHeight - mIndicatorHeight);
        canvas.drawPath(path, paint);
    }


    private void drawText(Canvas canvas, float textSize, String text, float transX) {

        mTextPaint.setTextSize(sp2px(textSize, getContext()));
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTypeface(mTypeface);
        String line1 = text.substring(0, text.indexOf("\r\n"));
        String line2 = text.substring(text.indexOf("\r\n") + 2);
        float line1Width = getTextWidth(line1, mTextPaint);
        float line2Width = getTextWidth(line2, mTextPaint);
        Paint.FontMetrics fm = mTextPaint.getFontMetrics();
        float textHeight = fm.descent - fm.ascent;
        float mVerticalMargin = (mTopHeight - 2 * textHeight) / 2f;
        float dp2 = dp2px(2, getContext()); // 消除toolbar阴影使文字看起来不垂直居中的影响
        if (textSize == mTextBigSize) {
            dp2 *= (mTextBigSize * 1.0f / mTextSmallSize);
        }
        if (line1.length() == 1) {
            canvas.drawText(line1, transX + mFirstColWidth / 2f - line1Width / 2f, mVerticalMargin + textHeight - dp2, mTextPaint);
            canvas.drawText(line2, transX + mFirstColWidth / 2f - line2Width / 2f, mTopHeight / 2f + textHeight - dp2, mTextPaint);
        } else {
            canvas.drawText(line1, transX + mColWidth / 2f - line1Width / 2f, mVerticalMargin + textHeight - dp2, mTextPaint);
            canvas.drawText(line2, transX + mColWidth / 2f - line2Width / 2f, mTopHeight / 2f + textHeight - dp2, mTextPaint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
        getColWidths();
        getTopHeight();
        mRowHeight = mHeight - mTopHeight;
        mIndicatorHeight = dp2px(5, getContext());
    }

    private static int dp2px(float dp, Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dp, context.getResources().getDisplayMetrics());
    }

    private static int sp2px(float sp, Context context) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                sp, context.getResources().getDisplayMetrics());
    }

    public float getTopHeight() {
        mTextPaint.setTextSize(sp2px(16, getContext()));
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float textHeight = (float) Math.ceil(fontMetrics.descent - fontMetrics.ascent);
        mTopHeight = 2 * mTopFrameMargin + 2 * textHeight;
        return mTopHeight;
    }

    private float getTextWidth(String src, Paint textPaint) {
        Rect rect = new Rect();
        textPaint.getTextBounds(src, 0, src.length(), rect);
        return rect.width();
    }

    public void getColWidths() {
        mTextPaint.setTextSize(sp2px(16, getContext()));
        Rect textBounds = new Rect();
        mTextPaint.getTextBounds(MONTH, 0, MONTH.length(), textBounds);
        mFirstColWidth = textBounds.width() + 2 * mTopFrameMargin;
        mColWidth = (mWidth - mFirstColWidth) / 7f;
    }

}
